﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ContourBuilder.Constraints;
using ITAP.Core.Modelling.Primitives;

using System.Drawing;
using ITAP.Core.Calculations;
using ITAP.Core.Modelling;

namespace ITAP.ContourBuilder.Components
{
    public interface IContourComponent : IContourVisitor, ICloneable
    {
        string Name { get; set; }
        IEnumerable<IContourComponent> ConnectedComponents { get; }
        IEnumerable<IContourComponent> InnerComponents { get; }
        IEnumerable<IContourConstraint> Constraints { get; }
        ICollection<IContourComponent> ComponentsInTolerance { get; }
        ICollection<Type> AcceptedTypesToConnect { get; }

        IPrimitive Primitive { get; set; }
        bool HasBoundingBox { get; set; }
        RectangleF BoundingBox { get; }
        void Update();

        IContourComponent ConnectTo(IContourComponent component);
        IContourComponent ConnectToEnded(IEndedContourComponent component, EndType endToConnect);
        IContourComponent DisconnectFrom(IContourComponent component);

        IContourComponent Parent { get; set; }
        int SerialNumber { get; set; }
        ModelPoint Position { get; }

        void MoveTo(ModelPoint destination);
        void MoveWithOffset(ModelVector offset);

        bool EnableConstraints { get; set; }

        bool Selected { get; set; }
        void SelectByPoint(ModelPoint point);
        bool CanSelectByPoint(ModelPoint point);
        double Tolerance { get; set; }
                                                                   
        /// <summary>
        /// Для всех компонент, примитивы и размеры которых зависят от текущего масштаба, размеров экрана и т.д.
        /// при изменении размеров контрола, представляющего модель, а также при изменении масштаба автоматически 
        /// вызывается этот метод.
        /// </summary>
        /// <param name="screenWidth"></param>
        /// <param name="screenHeight"></param>
        /// <param name="modelRectangle"></param>
        /// <param name="coordinateConverter"></param>
        void SetDisplayParameters(int screenWidth, int screenHeight, RectangleF modelRectangle, ModelCoordinateConverter coordinateConverter, ModelPoint cameraCenter);
        /// <summary>
        /// Если true, то перед получением актуального BoundingBox'а и примитива (если он задан), а также 
        /// перед вызовом всех методов, которые работают с примитивом (например, <see cref="SelectByPoint"/>),
        /// нужно вызвать метод <see cref="SetDisplayParameters"/>.
        /// </summary>
        bool IsPrimitiveDependsOnDisplayParameters { get; }

        void AcceptVisitor(IContourVisitor visitor);

        bool IsInTolerance(ModelPoint point, double tolerance);
        /// <summary>
        /// Если true, то компонент состоит из виртуальной точки, у которой нет соответствия размеров в модели (например, коннектор, соединяющий элементы контура).
        /// Если false, то компонент имеет размеры в модели.
        /// </summary>
        bool IsComponentDotted { get; }

        bool Modified { get; set; }
        int Id { get; set; }
    }
}
